package com.ray.tool.xml;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Ray框架 Xml 工具类
 * 依赖于dom4j包
 *
 * @author LiaoYuXing-Ray
 * @version 1.0
 * @createDate 2023/10/7 15:10
 **/
public class RayXmlTools {

    /**
     * 工具类中的方法都是静态方法访问的，因此将构造器私有不允许创建对象
     * 2023/10/7 15:01
     */
    private RayXmlTools(){
        throw new AssertionError();
    }


    /**
     * 判断传入字符串格式是否是xml格式字符串
     *
     * @param str 需要判断的字符串类型
     * @return boolean true为是
     * @author LiaoYuXing 2023/8/4 15:32
     **/
    public static boolean verifyStrIsXml(String str)  {
        boolean result = false;
        try {
            SAXReader reader = new SAXReader();
            Document document = reader.read(new StringReader(str));
            Element rootElement = document.getRootElement();
            if (rootElement != null) {
                result = true;
            }
        } catch (Exception ex) {
            // 传入字符串不是XML格式
        }
        return result;
    }


    /**
     * [Java对象]转化为[该对象的通用XML格式字符串]
     * 前提：该Java对象符合xml结构
     *
     * @param obj   Java对象
     * @param clazz 该对象的Java类
     * @return java.lang.String 该对象的通用XML格式字符串
     * @author LiaoYuXing 2023/8/17 9:59
     **/
    public static <T> String javaObjectToXmlStr(Object obj, Class<T> clazz) throws Exception {
        JAXBContext jaxbContext = JAXBContext.newInstance(clazz);
        Marshaller marshaller = jaxbContext.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
        StringWriter stringWriter = new StringWriter();
        marshaller.marshal(obj, stringWriter);
        return stringWriter.toString();
    }


    /**
     * 获取 XML 子元素对象集合
     *
     * @param objElement 父元素对象
     * @param qName      下一级子元素标签名称
     * @return java.util.List<org.dom4j.Element> 下一级子元素对象集合
     * @author LiaoYuXing 2023/8/4 11:38
     **/
    private static List<Element> getElementList(Element objElement, String qName) throws DocumentException {
        List<?> elementList;
        if (qName.equals("")) {
            elementList = objElement.elements(); // rootElement
        } else {
            elementList = objElement.element(qName).elements();
        }
        return elementList.stream().map(element -> (Element) element).collect(Collectors.toList());
    }

}
